R中按组匹配不同数据集中的值

Matching values in different datasets by groups in R

我有以下两个数据集:

df1 <- data.frame(
  "group" = c(1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5), 
  "numbers" = c(55, 75, 60, 55, 75, 60,  55, 75, 60,  55, 75, 60,  55, 75, 60))
df2 <- data.frame(
  "group" = c(1, 1, 2, 2, 2, 3, 3, 4, 5), 
  "P1" = c(55, NA, 60, 55, 75, 75, 55, 55, 60),
  "P2" = c(55, 75, 55, 60, NA, 75, 55, NA, 60),
  "P3" = c(75, 55, 60, 75, NA, 75, 60, 55, 60))

在df1中每组都有相同的三个号码(实际上大约有500个号码)。

我想检查df1中“numbers”列中的值是否包含在df2的P1、P2和P3列中。我遇到了两个问题。 1. df1的numbers列中的值可以出现在df2的不同组中(由df1和df2中的group列定义)。 2.数据集长度不同。有没有办法合并两个数据集并具有以下数据集:

df3 <- data.frame(
  "group"    = c(1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5), 
  "numbers"  = c(55, 75, 60, 55, 75, 60, 55, 75, 60, 55, 75, 60, 55, 75, 60,),
  "P1new"    = c(1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1),
  "P2new"    = c(1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1),
  "P3new"    = c(1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1))

如果 df2$P1 包含正确组内 df1$numbers 中的值,则 P1new(分别为 P2new 和 P3new)包含值 1(如我所说,数字可以在不同的组中重复出现)。例如,P3 在第 1 组中的值为 75,但在第 5 组中没有。因此,在第 1 组中,P3new 的值为 1,而在第 5 组中的 P3new 值为 0。 此题类似于 在 R 中按组查找不同数据集中的匹配值 但我无法根据我的目标调整代码。所以,我真的很感激任何帮助。

有趣的问题。这是 dplyr 函数的一种方式:

library(dplyr)
df2 %>% 
  group_by(group) %>% 
  summarise(across(P1:P3, ~ list(unique(na.omit(.x))))) %>% 
  inner_join(df1, .) %>% 
  rowwise() %>% 
  mutate(across(P1:P3, ~ +(numbers %in% .x)))

   group numbers    P1    P2    P3
   <dbl>   <dbl> <int> <int> <int>
 1     1      55     1     1     1
 2     1      75     0     1     1
 3     1      60     0     0     0
 4     2      55     1     1     0
 5     2      75     1     0     1
 6     2      60     1     1     1
 7     3      55     1     1     0
 8     3      75     1     1     1
 9     3      60     0     0     1
10     4      55     1     0     1
11     4      75     0     0     0
12     4      60     0     0     0
13     5      55     0     0     0
14     5      75     0     0     0
15     5      60     1     1     1

另一个可能的解决方案:

library(tidyverse)

map_dfc(names(df2[-1]), 
        ~ df1 %>%
          group_by(group) %>%
          mutate(!!.x := +(numbers %in% df2[df2$group == cur_group_id(), .x])) %>%
          ungroup %>%
          select(all_of(.x))) %>%
  bind_cols(df1, .)

#>    group numbers P1 P2 P3
#> 1      1      55  1  1  1
#> 2      1      75  0  1  1
#> 3      1      60  0  0  0
#> 4      2      55  1  1  0
#> 5      2      75  1  0  1
#> 6      2      60  1  1  1
#> 7      3      55  1  1  0
#> 8      3      75  1  1  1
#> 9      3      60  0  0  1
#> 10     4      55  1  0  1
#> 11     4      75  0  0  0
#> 12     4      60  0  0  0
#> 13     5      55  0  0  0
#> 14     5      75  0  0  0
#> 15     5      60  1  1  1

或者,没有purrr,另一种可能性:

library(dplyr)

df1 %>% 
  inner_join(df2) %>% 
  group_by(group) %>% 
  mutate(across(starts_with("P"), ~ +(numbers %in% .x))) %>% 
  ungroup %>% 
  distinct